#include "databasewindow.h"

#include "ui_databasewindow.h"
// #define NDEBUG
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
#include <QUrl>
#include <cassert>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include "inwindow.h"
#include "mysqlapi.h"
#include "out_excel.h"
#include "transassistanceqstring2string.h"

DatabaseWindow::DatabaseWindow(QWidget *parent)
    : QDialog(parent),
      ui(new Ui::DatabaseWindow) {
    ui->setupUi(this);
    ui->database_name->setText(str2qstr(MysqlAPI::database_));
}

DatabaseWindow::~DatabaseWindow() {
    delete ui;
}

void DatabaseWindow::AddNews(const QString &message) {
    ui->execute_log->append(message);
}

int DatabaseWindow::ExecuteAndUpdateLog(const QString &sentence) {
    return ExecuteAndUpdateLog(qstr2str(sentence));
}

int DatabaseWindow::ExecuteAndUpdateLog(const char *sentence) {
    return ExecuteAndUpdateLog(std::string(sentence));
}

int DatabaseWindow::ExecuteAndUpdateLog(const std::string &sentence) {
    ui->execute_log->append(QString("c++: %1").arg(sentence.c_str()));
    MysqlAPI::Connect(MysqlAPI::database_);
    int ret_error_code = MysqlAPI::Execute(sentence);  // record the error code
    if (ret_error_code == 2) {
        // fail
        ui->execute_log->append(QString("c++: Fail, the error code is %1.").arg(ret_error_code));
        ui->execute_log->append(QString("mysql: %s").arg(MysqlAPI::Error().c_str()));
    } else if (ret_error_code == 1) {
        // success, return nothing
        ui->execute_log->append(QString("c++: Success, but mysql return nothing."));
    } else if (ret_error_code == 0) {
        // success, return something
        ui->execute_log->append(QString("c++: Success."));
        ui->execute_log->append(QString("mysql: "));
        ans_ = std::move(MysqlAPI::Ans());
        for (auto p : ans_) {
            QString tmp;
            for (auto q : p) tmp.append((q + ", ").c_str());
            ui->execute_log->append(tmp);
        }
    }
    ui->execute_log->append("");
    MysqlAPI::Close();
    return ret_error_code;
}

void DatabaseWindow::on_init_database_clicked() {
    // show tips, prevent accidental click
    auto ret = QMessageBox::information(
        this, tr("提示"), tr("是否需要初始化？这将会清除原有数据库"),
        QMessageBox::Ok | QMessageBox::Cancel,
        QMessageBox::Cancel);
    if (QMessageBox::Cancel == ret) return;

    // init
    MysqlAPI::database_ = qstr2str(ui->database_name->text());  // update the name of database
    QString file_name = QFileDialog::getOpenFileName(           // 文件选择窗口，返回绝对路径字符串
        this,                                                   // 父类
        tr("选择你的初始化文件"),                               // 标题
        "../data",                                              // 默认打开位置
        tr("sql(*.sql)\nAll files(*.*)"));                      // 文件种类限制

    QString cmd = QString("mysql -h%1 -u%2 -p%3 -e \"source %4\"").arg(MysqlAPI::host_.c_str(), MysqlAPI::user_.c_str(), MysqlAPI::password_.c_str(), file_name);
    QProcess sub_process;  // sub process
    sub_process.start(cmd);
    sub_process.waitForFinished();
    ui->execute_log->append(cmd);
    ui->execute_log->append(sub_process.readAll());
    ui->execute_log->append(sub_process.readAllStandardError());  // stderr
    // show tips
    QMessageBox::information(this, tr("执行结果"), tr("初始化成功！"));
    // record the name of database
    // QFile file(file_name);
    // file.open(QIODevice::ReadOnly);
    // while (!file.atEnd()){
    //     std::string row = qstr2str(file.readLine());
    //     if (std::string::npos != row.find("use")) {
    //         MysqlAPI::database_ = std::string(row.begin() + row.rfind(' '), row.begin() + row.rfind(';'));
    //         ui->database_name->setText(str2qstr(MysqlAPI::database_));
    //         break;
    //     }
    // }
    // file.close();
}

void DatabaseWindow::on_in_clicked() {
    InWindow tmp(this, 1);
    tmp.exec();  // 阻塞执行
}

void DatabaseWindow::on_out_clicked() {
    InWindow tmp(this, 0);
    tmp.exec();  // 阻塞执行
}

void DatabaseWindow::on_select_item_clicked() {
    ExecuteAndUpdateLog("select * from items;");
    std::ofstream fout;
    fout.open("../data/ans.csv");
    assert(fout.is_open());
    fout << "ID, name, unit, standard, source, total_amount, \n";
    for (auto &row : ans_) {
        for (auto &p : row) fout << p << ", ";
        fout << "\n";
    }
    fout.close();
    auto file_dir = qstr2str(QDir::currentPath());
    file_dir = std::string(file_dir.begin(), file_dir.begin() + file_dir.rfind('/')) + "/data/";
    QDesktopServices::openUrl(QUrl(file_dir.c_str(), QUrl::TolerantMode));
}

void DatabaseWindow::on_select_in_clicked() {
    ExecuteAndUpdateLog("select * from `in` natural join items;");
    std::ofstream fout;
    fout.open("../data/ans.csv");
    assert(fout.is_open());
    fout << "ID, in_ID, amount, unit_price, total_price, time, note, operator, name, unit, standard, source, \n";
    for (auto &row : ans_) {
        for (auto &p : row) fout << p << ", ";
        fout << "\n";
    }
    fout.close();
    auto file_dir = qstr2str(QDir::currentPath());
    file_dir = std::string(file_dir.begin(), file_dir.begin() + file_dir.rfind('/')) + "/data/";
    QDesktopServices::openUrl(QUrl(file_dir.c_str(), QUrl::TolerantMode));
}

void DatabaseWindow::on_select_out_clicked() {
    ExecuteAndUpdateLog("select * from `out` natural join items;");
    std::ofstream fout;
    fout.open("../data/ans.csv");
    assert(fout.is_open());
    fout << "ID, out_ID, amount, unit_price, total_price, time, note, operator, name, unit, standard, source, \n";
    for (auto &row : ans_) {
        for (auto &p : row) fout << p << ", ";
        fout << "\n";
    }
    fout.close();
    auto file_dir = qstr2str(QDir::currentPath());
    file_dir = std::string(file_dir.begin(), file_dir.begin() + file_dir.rfind('/')) + "/data/";
    QDesktopServices::openUrl(QUrl(file_dir.c_str(), QUrl::TolerantMode));
}

void DatabaseWindow::on_select_log_clicked() {
    QString sentence = "(select log_ID, in_ID, out_ID, ID, name, unit, standard, source, total_amount, amount, unit_price, total_price, time, note, operator from log natural join (`in` natural join `items`))"
                           "union"
                           "(select log_ID, in_ID, out_ID, ID, name, unit, standard, source, total_amount, amount, unit_price, total_price, time, note, operator from log natural join (`out` natural join `items`))"
                           "order by log_ID;";
    ExecuteAndUpdateLog(sentence);
    std::ofstream fout;
    fout.open("../data/ans.csv");
    assert(fout.is_open());
    fout << "log_ID, in_ID, out_ID, ID, name, unit, standard, source, total_amount, amount, unit_price, total_price, time, note, operator, \n";
    for (auto &row : ans_) {
        for (auto &p : row) fout << p << ", ";
        fout << "\n";
    }
    fout.close();
    auto file_dir = qstr2str(QDir::currentPath());
    file_dir = std::string(file_dir.begin(), file_dir.begin() + file_dir.rfind('/')) + "/data/";
    QDesktopServices::openUrl(QUrl(file_dir.c_str(), QUrl::TolerantMode));
}



